Skip to content

Conversation

@macarte
Copy link
Contributor

@macarte macarte commented Oct 28, 2025

Add jdk.management.AOTCacheMXBean. The interface provides a single action that when called will cause any hosted JVM currently recording AOT information will stop recording. Existing functionality is preserved: when stopped the JVM will create the required artifacts based on the execution mode. Conveniently as the application running on the JVM has not stopped (as was previously the only way to stop recording), the application will resume execution after the artifacts have been generated.

The interface will return TRUE if a recording was successfully stopped, in all other cases (not recording etc.) will return FALSE

It follows that invoking the action on a JVM that is recording, twice in succession, should (baring internal errors) produce the following two responses:

TRUE
FALSE

Passes tier1 on linux (x64) and windows (x64)


Progress

  • Change must be properly reviewed (1 review required, with at least 1 Reviewer)
  • Change must not contain extraneous whitespace
  • Commit message must refer to an issue
  • Change requires CSR request JDK-8369737 to be approved

Integration blocker

 ⚠️ Dependency #27965 must be integrated first

Issues

  • JDK-8369736: Add management interface for AOT cache creation (Enhancement - P3)
  • JDK-8369737: Add management interface for AOT cache creation (CSR)

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/28010/head:pull/28010
$ git checkout pull/28010

Update a local copy of the PR:
$ git checkout pull/28010
$ git pull https://git.openjdk.org/jdk.git pull/28010/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 28010

View PR using the GUI difftool:
$ git pr show -t 28010

Using diff file

Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/28010.diff

Using Webrev

Link to Webrev Comment

@bridgekeeper
Copy link

bridgekeeper bot commented Oct 28, 2025

👋 Welcome back macarte! A progress list of the required criteria for merging this PR into pr/27965 will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

@openjdk
Copy link

openjdk bot commented Oct 28, 2025

❗ This change is not yet ready to be integrated.
See the Progress checklist in the description for automated requirements.

@openjdk
Copy link

openjdk bot commented Oct 28, 2025

@macarte The following labels will be automatically applied to this pull request:

  • hotspot
  • jmx
  • serviceability

When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing lists. If you would like to change these labels, use the /label pull request command.

@openjdk openjdk bot added the rfr Pull request is ready for review label Oct 28, 2025
@mlbridge
Copy link

mlbridge bot commented Oct 28, 2025

* </blockquote>
*
* @return {@code true} if a recording was in progress and has been ended successfully; {@code false} otherwise.
*/
Copy link
Contributor

@AlanBateman AlanBateman Oct 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are issues in the javadoc that will cause the docs target to fail, e.g. mismatched blockquote. Can you fix these up so that we can generate the docs from the changes in the PR?

Copy link
Contributor Author

@macarte macarte Oct 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there an easy way to test the correctness of the javadoc parts (I couldn't find an option for javadoc). The </blockquote >above is matched to a <blockquote> on line 88, but there is a <pre></pre> pair in between, is that the issue you are referring to?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make docs. The second blockquote is matched with another blockquote, not </blockquote>. In the example, which can be converted to a snippet, then then braces not matched so the end brace for {@code ... } get mixed up.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that now - fixing ....

Copy link
Contributor Author

@macarte macarte Oct 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also removed the nested {@code ..} from within the <pre></pre> as that also caused an issue

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good. You can move the example to a snippet too and that will allow the <pre> tags to go away.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the latest CSR the code snippet was removed

class HotSpotAOTCacheMXBeanApp {
public static void main(String[] args) {
System.out.println("Hello Leyden " + args[0]);
var aotBean = ManagementFactory.getPlatformMXBean(HotSpotAOTCacheMXBean.class);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This uses MF.getPlatformMXBean in the child VM. A more complete test would repeat with:

        MBeanServer server = ManagementFactory.getPlatformMBeanServer();
        HotSpotAOTCacheMXBean bean = ManagementFactory.newPlatformMXBeanProxy(server,
                "jdk.management:type=HotSpotAOTCacheMXBean",
                HotSpotAOTCacheMXBean.class);

In any case, it might be simpler to test that the MXBean is registered in the test itself, it doesn't need to be in the child VM.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Alan, I changed the code per your recommendation to not use ManagementFactory.getPlatformMXBean

@openjdk
Copy link

openjdk bot commented Oct 29, 2025

⚠️ @macarte This pull request contains merges that bring in commits not present in the target repository. Since this is not a "merge style" pull request, these changes will be squashed when this pull request in integrated. If this is your intention, then please ignore this message. If you want to preserve the commit structure, you must change the title of this pull request to Merge <project>:<branch> where <project> is the name of another project in the OpenJDK organization (for example Merge jdk:master).

* }
* </pre></blockquote>
*
* @return {@code true} if a recording was in progress and has been ended successfully; {@code false} otherwise.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Someone is bound to ask what happens if the "endRecording" operation is performed concurrently and there is recording in progress. Does one or all return true? I don't think it matters, the bigger issue here is that returning false means the recording has already ended or it failed. If it failed, why did it fail? I realize the intention is to add some properties and further operations to this MXBean but I think it would be good to think through if starting with a boolean returning operation is going to be problematic in the future.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see a couple of cases for when endRecording is called:

  1. Within the same process to generate a cache - given the api will only return true to one caller, that caller is the only one who can be responsible for taking further action (copying the cache somewhere, etc). Already ended or failed makes no difference operationally.

  2. From a monitoring process - again only the successful case matters. All failures (already ended or failed) are indistinguishable. No further action can be taken by the observer. It's only the success case that matters

@egahlin
Copy link
Member

egahlin commented Nov 3, 2025

Can this be done using a diagnostic command, e.g. AOT.stop? It would allow the recording to be stopped from jcmd and the DiagnosticCommandMBean, without the need for a separate MXBean.

@macarte
Copy link
Contributor Author

macarte commented Nov 3, 2025

Can this be done using a diagnostic command, e.g. AOT.stop? It would allow the recording to be stopped from jcmd and the DiagnosticCommandMBean, without the need for a separate MXBean.

Thank you for the suggestion

To answer your first question, we do have a diagnostic command (AOT.end_recording) and it would precede the AOT MXBean into mainline and its PR is here: #27965

The longer goal for this MXBean is to provide additional methods that would aid in monitoring (isRecording, currentRecordingLength etc.), however we decided to reduce the scope of the MXBean for main line while we continue to test the monitoring functionality in leyden/premain

Historically the diagnostic command came after the MXBean in leyden/premain, however I decided to implement the diagnostic command with the necessary JVM hooks first to simplify review

So technically we could delay this PR and still have the required functionality in mainline, I'd like to hear from the other reviewers on this matter

@egahlin
Copy link
Member

egahlin commented Nov 4, 2025

To answer your first question, we do have a diagnostic command (AOT.end_recording) and it would precede the AOT MXBean into mainline and its PR is here: #27965

Ah, I didn't know that.

(I don’t have a strong opinion on this, but for consistency you might want the jcmd commands for AOT recording to use the same naming convention for starting, stopping, and checking the status of a recording as JFR: JFR.start, JFR.stop, JFR.check, JFR.dump and JFR.configure, where applicable. Initially, we had start_recording, but we later shortened it to start to avoid unnecessary typing)

The longer goal for this MXBean is to provide additional methods that would aid in monitoring (isRecording, currentRecordingLength etc.), however we decided to reduce the scope of the MXBean for main line while we continue to test the monitoring functionality in leyden/premain

Historically the diagnostic command came after the MXBean in leyden/premain, however I decided to implement the diagnostic command with the necessary JVM hooks first to simplify review

Ok.

* <p>For more information about creating and using the AOT artifacts, and detailed
* specification of the corresponding JVM command-line options, please refer
* to https://openjdk.org/jeps/483 and https://openjdk.org/jeps/514.
*
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't use bare URLs. Change these to

... please refer to JEPs <a href="https://openjdk.org/jeps/483">483</a> and
<a href="https://openjdk.org/jeps/514">514</a>.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@openjdk openjdk bot removed the csr Pull request needs approved CSR before integration label Nov 11, 2025
…ke AOT.end_recording"

Commit was intended for parent branch (that this branch is based on)

This reverts commit bff7cb7.
@macarte macarte requested a review from mbreinhold November 13, 2025 18:53
@openjdk openjdk bot removed the rfr Pull request is ready for review label Nov 13, 2025
@openjdk openjdk bot added the rfr Pull request is ready for review label Nov 13, 2025
@AlanBateman
Copy link
Contributor

I went through the plumbing to check the registration with the platform MBeanServer and everything looks okay (and consistent with how the other JDK-specific management interfaces are setup and registered).

* @return {@code true} if a recording was in progress and has been ended
* successfully; {@code false} otherwise.
*/
public boolean endRecording();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor nit is that we usually use 4-space rather than 2-space indent in the java sources. You might want to check the /** .. */ comments in a few of the files as they are misaligned in a few places.

* @summary Sanity test for HotSpotAOTCache MXBean
* @requires vm.cds.write.archived.java.heap
* @library /test/jdk/lib/testlibrary /test/lib
* /test/hotspot/jtreg/runtime/cds/appcds/aotCache/test-classes
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is test-classes used?

import jdk.test.lib.helpers.ClassFileInstaller;
import jdk.test.lib.process.OutputAnalyzer;

public class HotSpotAOTCacheMXBeanTest {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In addition to testing the endRecording operation, we also need to test both the direct and indirect access to the MXBean. The test currently obtains a proxy with newPlatformMXBeanProxy (good) but the direct access with ManagementFactory.getPlatformMXBean is not tested right now.

Another thing to test is that getObjectName returns the expected object name.

out.shouldContain("Failed to stop recording");
}
out.shouldNotContain("HotSpotAOTCacheMXBean is not available");
out.shouldNotContain("IOException occurred!");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you considering have the child terminate with an exception so the exit status is non-0. If you get a success status then the output should have the expected strings. A non-0 would failure, and the test fails.

this.jvm = vm;
}

public boolean endRecording(){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

trivial missing space nit (){

public Map<String, HotSpotAOTCacheMXBean> nameToMBeanMap() {
HotSpotAOTCacheMXBean impl = this.impl;
if (impl == null) {
this.impl = impl = new HotSpotAOTCacheImpl(ManagementFactoryHelper.getVMManagement());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assignment is unusual. Are we trying to avoid a synchronized block? Other nameToMBeanMap() methods are like:
return Collections.singletonMap(ManagementFactory.MEMORY_MXBEAN_NAME, ManagementFactoryHelper.getMemoryMXBean());

..where the ManagementFactoryHelper.getMemoryMXBean() method is synchronized and creates the impl if needed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see a correctly issue with this. Maybe in the future we will be able to use LazyConstant here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

7 participants